package com.google.wave.extensions.code.eval;

/**
 * {@code CodeResultFactory} creates {@link CodeResult} objects.
 *
 * @author schwardo@google.com (Don Schwarz)
 */
class CodeResultFactory {
    private static final CodeResult NULL_RESULT = new NullResult();

    public static CodeResult getSuccessfulResult(Object returnValue) {
	if (returnValue == null) {
	    return NULL_RESULT;
	} else {
	    return new SuccessResult(returnValue.toString());
	}
    }

    public static CodeResult getErrorResult(Throwable throwable) {
	return getErrorResult(throwable, CodeResult.UNKNOWN, CodeResult.UNKNOWN);
    }

    public static CodeResult getErrorResult(Throwable throwable, int lineNumber, int colNumber) {
	return new ErrorResult(throwable.getMessage(), lineNumber, colNumber);
    }

    private static class NullResult implements CodeResult {
	public boolean isSuccess() {
	    return true;
	}

	public boolean hasReturnValue() {
	    return false;
	}

	public String getReturnValueString() {
            return "null";
	}

	public int getErrorLineNumber() {
	    throw new IllegalStateException();
	}

	public int getErrorColumnNumber() {
	    throw new IllegalStateException();
	}

	public String getErrorMessage() {
	    throw new IllegalStateException();
	}
    }

    private static class SuccessResult implements CodeResult {
	private final String returnValueString;

	public SuccessResult(String returnValueString) {
	    this.returnValueString = returnValueString;
	}

	public boolean isSuccess() {
	    return true;
	}

	public boolean hasReturnValue() {
	    return true;
	}

	public String getReturnValueString() {
	    return returnValueString;
	}

	public int getErrorLineNumber() {
	    throw new IllegalStateException();
	}

	public int getErrorColumnNumber() {
	    throw new IllegalStateException();
	}

	public String getErrorMessage() {
	    throw new IllegalStateException();
	}
    }

    private static class ErrorResult implements CodeResult {
	private final String errorMessage;
	private final int lineNumber;
	private final int colNumber;

	public ErrorResult(String errorMessage, int lineNumber, int colNumber) {
	    this.errorMessage = errorMessage;
	    this.lineNumber = lineNumber;
	    this.colNumber = colNumber;
	}

	public boolean isSuccess() {
	    return false;
	}

	public boolean hasReturnValue() {
	    return false;
	}

	public String getReturnValueString() {
	    throw new IllegalStateException();
	}

	public int getErrorLineNumber() {
	    return lineNumber;
	}

	public int getErrorColumnNumber() {
	    return colNumber;
	}

	public String getErrorMessage() {
	    return errorMessage;
	}
    }

}
